import { Animation } from "./Animation.js";
import { Vector2 } from "./Vector2.js";

let onAnimationFrameCallback = null
function onAnimationFrame(time) {
    if (onAnimationFrameCallback) onAnimationFrameCallback(time);
}

class Render {
    constructor(parameters = {}) {
        this._canvas = parameters.canvas !== undefined ? parameters.canvas : this.createCanvasElement()
        this._context = parameters.context !== undefined ? parameters.context : this._canvas.getContext('2d')

        this._width = this._canvas.width;
        this._height = this._canvas.height;
        this._pixelRatio = 1

        this.domElement = this._canvas;
    }
    createCanvasElement() {
        let canvas = document.createElementNS('http://www.w3.org/1999/xhtml', 'canvas')
        canvas.style.display = 'block'

        return canvas
    }
    setSize(width, height, updateStyle = true) {

        this._width = width * this._pixelRatio;
        this._height = height * this._pixelRatio;

        this._canvas.width = Math.floor(width * this._pixelRatio);
        this._canvas.height = Math.floor(height * this._pixelRatio);

        if (updateStyle !== false) {
            this._canvas.style.width = width + 'px';
            this._canvas.style.height = height + 'px';
        }
    }
    setPixelRatio(value) {
        if (value === undefined) return;

        this._pixelRatio = value;
        this.setSize(this._width, this._height, false);
    }

    setTickLength(tickLength) {
        if (this.animation) {
            this.animation.setTickLength(tickLength)
        } else {
            this.animation_fps = tickLength
        }
    }

    setAnimationLoop(callback) {
        this.animation = new Animation()
        if (this.animation_fps) {
            this.animation.setTickLength(this.animation_fps)
        }
        this.animation.setAnimationLoop(onAnimationFrame)
        onAnimationFrameCallback = callback
        if (callback === null) {
            this.animation.stop()
        } else {
            this.animation.start()
        }
    }

    animate(item) {
        if (item.name === 'range') return
        const positions = item.attributes.position
        if (positions && positions.length > 0) {
            let outLeft = 0, outRight = 0, outTop = 0, outBottom = 0
            const that = this
            positions.forEach(pos => {
                pos = Vector2.add(item.position, pos)
                // left
                if (pos.x < 0 && pos.x < outLeft) {
                    outLeft = pos.x
                }
                // right
                if (pos.x > that._width && pos.x > outRight + that._width) {
                    outRight = pos.x - that._width
                }
                // top
                if (pos.y < 0 && pos.y < outTop) {
                    outTop = pos.y
                }
                // bottom
                if (pos.y > that._height && pos.y > outBottom + that._height) {
                    outBottom = pos.y - that._height
                }
            })
            // console.log(item.position)
            let horizontal = (outLeft + outRight) * -1
            let vertical = (outTop + outBottom) * -1
            item.force.add(Vector2.mul(new Vector2(horizontal, vertical), 1))
            // console.log(new Vector2(horizontal, vertical))
        }

        item.velocity.add(Vector2.mul(item.force, 1))
        item.force.mul(0)
        // item.force.y = .099
        item.position.add(item.velocity)
        item.pointerTo()
    }

    render(scene) {
        this.renderList = []
        this.projectObject(scene)
        for (let i = 0, il = this.renderList.length; i < il; i++) {
            const renderItem = this.renderList[i]
            if (renderItem.isScene) {
                this._context.clearRect(0, 0, this._width * this._pixelRatio, this._height * this._pixelRatio)
            } else if (renderItem.isText) {
                this.animate(renderItem)
                renderItem.draw(this._context)
            } else {
                this.animate(renderItem)

                const position = renderItem.attributes.position;
                // const position = renderItem.getPositions();

                if (position) {
                    this._context.beginPath()
                    let vector = Vector2.add(renderItem.position, position[0])
                    this._context.moveTo(vector.x, vector.y)
                    for (let j = 1, jl = position.length; j < jl; j++) {
                        vector = Vector2.add(renderItem.position, position[j])
                        this._context.lineTo(vector.x, vector.y)
                    }
                    if (renderItem.attributes.close) {
                        vector = Vector2.add(renderItem.position, position[0])
                        this._context.lineTo(vector.x, vector.y)
                    }
                    if (renderItem.attributes.stroke) {
                        this._context.strokeStyle = renderItem.attributes.strokeStyle
                        this._context.stroke()
                    } else {
                        this._context.fillStyle = renderItem.attributes.fillStyle
                        this._context.fill()
                    }
                    // console.log(position)
                    this._context.closePath()
                }
            }
        }
    }

    projectObject(object) {
        if (object.visible === false) return
        this.renderList.push(object)
        for (let i = 0, l = object.children.length; i < l; ++i) {
            this.projectObject(object.children[i])
        }
    }
}

export { Render }